标签
安全
字数
2998 字
阅读时间
17 分钟
配置过滤器
java
import com.alibaba.fastjson.JSON;
import com.commnetsoft.commons.Result;
import com.commnetsoft.commons.utils.StringUtils;
import com.commnetsoft.exception.MicroRuntimeException;
import com.commnetsoft.zuul.RouteRuntimeException;
import com.commnetsoft.zuul.service.WebMvcRouteService;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;
/**
* 前置路由JWT 过滤器<br/>
* 内部地址.fn统一禁止外部访问
* <br/>
* pre: 请求执行之前
* <p>
* route: 处理请求,进行路由
* <p>
* post: 请求处理完成后执行
* <p>
* error: 出现错误时执行
* author Brack.zhu
* date 2019/3/27
*/
@Component
public class ZuulJwtFilter extends ZuulFilter {
private Logger log = LoggerFactory.getLogger(ZuulJwtFilter.class);
@Autowired
private WebMvcRouteService webMvcRouteService;
/**
* 前置过滤器
*
* @return
*/
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
/**
* 装载顺序越小越先执行
*
* @return
*/
@Override
public int filterOrder() {
return FilterConstants.FORM_BODY_WRAPPER_FILTER_ORDER;
}
/**
* 过滤器是否生效
*
* @return true需要权限校验,false不需要用户校验即可访问
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 业务逻辑
* 只有过滤器生效,才会进入到该方法
*/
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
try {
HttpServletRequest request = requestContext.getRequest();
Map<String, String> verifyData = webMvcRouteService.verifyUri(request);
if (null != verifyData) {
//认证头数据
Iterator<Map.Entry<String, String>> entries = verifyData.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String, String> entry = entries.next();
requestContext.addZuulRequestHeader(entry.getKey(), URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.name()));
}
//TODO 移除请求头数据,如jwt
}
}catch (RouteRuntimeException rre) {
requestInvalid(requestContext, rre);
}catch (MicroRuntimeException mre){
requestInvalid(requestContext,new RouteRuntimeException(mre, HttpStatus.FORBIDDEN));
}catch (Exception e) {
log.error("前置路由过滤器异常:", e);
// ZuulException 返回数据格式
// {
// "timestamp": "2020-09-28 14:41:11",
// "status": 500,
// "error": "Internal Server Error",
// "message": "exception message"
//}
throw new ZuulException(e, HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getLocalizedMessage());
}
return null;
}
/**
* 请求无效处理
*
* @param requestContext
* @param routeRuntimeException
*/
public void requestInvalid(RequestContext requestContext, RouteRuntimeException routeRuntimeException) {
String respJson=JSON.toJSONString(Result.create(routeRuntimeException)) ;
requestInvalid(requestContext, routeRuntimeException.getStatus(),respJson);
}
/**
* 请求无效处理
*
* @param requestContext
* @param httpStatus 返回http错误码
* @param respBody 返回的内容
*/
public void requestInvalid(RequestContext requestContext, HttpStatus httpStatus,String respBody) {
// 过滤该请求,不对其进行路由
requestContext.setSendZuulResponse(false);
//错误代码
requestContext.setResponseStatusCode(httpStatus.value());
if(StringUtils.isNotBlank(respBody)){
requestContext.setResponseBody(respBody);
}
requestContext.getResponse().setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
}
}处理类
java
import com.commnetsoft.auth.model.HttpReqHead;
import com.commnetsoft.commons.utils.StringUtils;
import com.commnetsoft.core.utils.HttpRequestUtil;
import com.commnetsoft.zuul.RouteRuntimeException;
import com.commnetsoft.zuul.UriType;
import com.commnetsoft.zuul.uri.IUriHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* WebMvc路由服务<br/>
* 使用需要在Configuration中声明
*
* @author Brack.zhu
* @date 2020/6/3
*/
@Service
public class WebMvcRouteService extends RouteService {
private Logger log = LoggerFactory.getLogger(WebMvcRouteService.class);
/**
* URI地址权限校验
*
* @return
*/
public Map<String, String> verifyUri(HttpServletRequest servletRequest) throws RouteRuntimeException {
String uri = servletRequest.getRequestURI();
String method = servletRequest.getMethod();
UriType uriType = super.convertUri(uri);
List<String> keys = super.headerKeys(uriType);
Map<String, String> headers = getHeaders(servletRequest, keys);
String contentType = servletRequest.getContentType();
InputStream inputStream = null;
if (isBodyData(uriType, contentType)) {
try {
inputStream = servletRequest.getInputStream();
} catch (IOException e) {
if (log.isDebugEnabled()) {
log.debug("获取{}输入流异常", uri);
}
}
}
return super.verifyUri(uri, uriType, method, headers, inputStream);
}
/**
* 获取指定的头数据
*
* @param servletRequest
* @param keys
* @return
*/
public Map<String, String> getHeaders(HttpServletRequest servletRequest, List<String> keys) {
if (null == keys) {
return null;
}
Map<String, String> headers = new HashMap<>();
for (String key : keys) {
if (IUriHandler.EXTEND_HEADER_REQUEST_REMOTE_ADDRESS.equals(key)) {
//特殊
String headerVal = servletRequest.getRemoteAddr();
headers.put(key, headerVal);
} else if (HttpReqHead.token.getValue().equals(key) || HttpReqHead.token_old.getValue().equals(key)) {
//特殊 token 头获取失败从cookie中取
String headerVal = servletRequest.getHeader(key);
if (StringUtils.isEmpty(headerVal)) {
headerVal = HttpRequestUtil.getCookieVal(servletRequest, key);
}
headers.put(key, headerVal);
} else {
String headerVal = servletRequest.getHeader(key);
headers.put(key, headerVal);
}
}
return headers;
}
}
import com.commnetsoft.core.CommonError;
import com.commnetsoft.exception.MicroRuntimeException;
import com.commnetsoft.zuul.RouteRuntimeException;
import com.commnetsoft.zuul.UriType;
import com.commnetsoft.zuul.feign.AuthResApi;
import com.commnetsoft.zuul.uri.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
/**
* 路由业务服务<br/>
* 顺序变化会对业务有影响<br/>
* <ol>
* <li>resource</li>
* <li>open</li>
* <li>external</li>
* <li>internal</li>
* </ol>
*
* @author Brack.zhu
* @date 2020/5/27
*/
public abstract class RouteService {
@Autowired
protected AuthResApi authResApi;
@Autowired
protected InternalApiUriHandler internalApiUriHandler;
@Autowired
protected ExternalApiUriHandler externalApiUriHandler;
@Autowired
protected OpenApiUriHandler openApiUriHandler;
@Autowired
protected ResourceUriHandler resourceUriHandler;
@Autowired
protected WebsocketUriHandler websocketUriHandler;
private Logger log = LoggerFactory.getLogger(RouteService.class);
/**
* 解析JWT
*
* @param jwt
* @return
* @throws MicroRuntimeException
*/
public Map<String, String> parseJwt(String jwt) throws MicroRuntimeException {
return authResApi.jwtParse(jwt).tryData();
}
/**
* URI地址权限校验<br>
*
* @return
*/
public Map<String, String> verifyUri(String uri, UriType uriType, String method, Map<String, String> headers, InputStream in) throws RouteRuntimeException {
IUriHandler uriHandler = getUriHandler(uriType);
if (null != uriHandler) {
return uriHandler.verifyUri(uri, method, headers, in);
} else {
log.warn("根据{},{}获取处理器失败,", uriType, uri);
throw new RouteRuntimeException(CommonError.unsupport,"未获取对应URI过滤器:"+uriType,HttpStatus.FORBIDDEN);
}
}
/**
* 获取地址类型
* 判断条件根据预判的调用程度排先后顺序
*
* @param uri
* @return
*/
public UriType convertUri(String uri) {
if (websocketUriHandler.isSupport(uri)){
return websocketUriHandler.handlerType();
}
if (resourceUriHandler.isSupport(uri)) {
return resourceUriHandler.handlerType();
}
if (openApiUriHandler.isSupport(uri)) {
return openApiUriHandler.handlerType();
}
if (externalApiUriHandler.isSupport(uri)) {
return externalApiUriHandler.handlerType();
}
if (internalApiUriHandler.isSupport(uri)) {
return internalApiUriHandler.handlerType();
}
return UriType.UNDEFINED_URI;
}
/**
* 根据URI类型获取请求头参数key集合
*
* @param uritype
* @return
*/
public List<String> headerKeys(UriType uritype) {
IUriHandler uriHandler = getUriHandler(uritype);
if (null != uriHandler) {
return uriHandler.headerKeys();
}
return null;
}
/**
* 根据URI类型判断是否需要请求数据
*
* @param uritype
* @param contentType
* @return
*/
public boolean isBodyData(UriType uritype,String contentType) {
IUriHandler uriHandler = getUriHandler(uritype);
if (null != uriHandler) {
return uriHandler.isBodyData(contentType);
}
return false;
}
/**
* 根据URI类型获取处理对象
*
* @param uritype
* @return
*/
public IUriHandler getUriHandler(UriType uritype) {
switch (uritype) {
case WEBSOCKET_URI:
return websocketUriHandler;
case OPEN_API_URI:
return openApiUriHandler;
case INTERNAL_API_URI:
return internalApiUriHandler;
case EXTERNAL_API_URI:
return externalApiUriHandler;
case RESOURCE_URI:
return resourceUriHandler;
default:
return null;
}
}
/**
* 是否内部接口地址类型
*
* @param uri
* @return
*/
public boolean isInternalApiUri(String uri) {
return internalApiUriHandler.isSupport(uri);
}
/**
* 是否外部接口地址类型
*
* @param uri
* @return
*/
public boolean isExternalApiUri(String uri) {
return externalApiUriHandler.isSupport(uri);
}
/**
* 是否开放接口地址类型
*
* @param uri
* @return
*/
public boolean isOpenApiUri(String uri) {
return openApiUriHandler.isSupport(uri);
}
/**
* 是否资源地址类型
*
* @param uri
* @return
*/
public boolean isResourceUri(String uri) {
return resourceUriHandler.isSupport(uri);
}
}地址处理类
java
import com.commnetsoft.commons.utils.StringUtils;
import com.commnetsoft.core.CoreConstant;
import com.commnetsoft.zuul.RouteRuntimeException;
import com.commnetsoft.zuul.UriType;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
/**
* 地址处理器接口
*
* @author Brack.zhu
* @date 2020/6/2
*/
public interface IUriHandler {
/**
* 获取request远程地址头 key---特殊未经过负载层的
*/
String EXTEND_HEADER_REQUEST_REMOTE_ADDRESS = "Extend_Request_Remote_Address_Header_Key";
/**
* 处理器支持处理类型
*
* @return
*/
UriType handlerType();
/**
* 是否支持的地址类型
*
* @param uri
* @return
*/
boolean isSupport(String uri);
/**
* 获取该处理器需要的头数据的key集合
*
* @return
*/
List<String> headerKeys();
/**
* 判断该处理器是否需求请求体数据
* @param contentType 请求类型
* @return
*/
boolean isBodyData(String contentType);
/**
* URI地址权限校验
*
* @param uri
* @param method
* @param headers
* @param in
* @return 有效jwt对应的信息
* @throws RouteRuntimeException 校验异常
*/
Map<String, String> verifyUri(String uri, String method, Map<String, String> headers, InputStream in);
/**
* 获取头IP数据
*
* @param headers
* @return
*/
default String getHeaderIp(Map<String, String> headers) {
if (null == headers) {
return null;
}
String ip = headers.get(CoreConstant.Http.HEADER_REAL_IP);
if (StringUtils.isEmpty(ip)) {
ip = headers.get(EXTEND_HEADER_REQUEST_REMOTE_ADDRESS);
}
return ip;
}
}java
import com.commnetsoft.auth.model.HttpReqHead;
import com.commnetsoft.commons.utils.StringUtils;
import com.commnetsoft.commons.utils.UriUtil;
import com.commnetsoft.core.CommonError;
import com.commnetsoft.exception.MicroRuntimeException;
import com.commnetsoft.zuul.RouteRuntimeException;
import com.commnetsoft.zuul.UriType;
import com.commnetsoft.zuul.service.AuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 外部接口地址处理器实现类
*
* @author Brack.zhu
* @date 2020/6/2
*/
@Component
public class ExternalApiUriHandler implements IUriHandler {
public static final String JWT = "jwt";
@Autowired
private AuthService authService;
private List<String> headerKeys;
public ExternalApiUriHandler() {
headerKeys = new ArrayList<>(2);
headerKeys.add(HttpReqHead.token.getValue());
//兼容老的
headerKeys.add(HttpReqHead.token_old.getValue());
}
@Override
public UriType handlerType() {
return UriType.EXTERNAL_API_URI;
}
@Override
public List<String> headerKeys() {
return headerKeys;
}
@Override
public boolean isBodyData(String contentType) {
return false;
}
@Override
public Map<String, String> verifyUri(String uri, String method, Map<String, String> headers, InputStream in) {
try {
String jwt = getHeaderToken(headers);
return authService.uriVerify(uri, method, jwt);
} catch (MicroRuntimeException mre) {
if (mre.getCode().toLowerCase().contains(JWT)) {
throw new RouteRuntimeException(mre,HttpStatus.NOT_ACCEPTABLE);
} else {
throw new RouteRuntimeException(mre,HttpStatus.FORBIDDEN);
}
}catch (Exception e){
throw new RouteRuntimeException(CommonError.internal_error,e.getMessage(),HttpStatus.FORBIDDEN);
}
}
@Override
public boolean isSupport(String uri) {
String ext = UriUtil.getFileExtension(uri);
if (StringUtils.isBlank(ext)) {
//没有后缀的定义为外部接口
return true;
}
return false;
}
/**
* 获取{@link HttpReqHead#token} 值
* @param headers
* @return
*/
String getHeaderToken(Map<String,String> headers){
if(null==headers){
return null;
}
String jwt=headers.get(HttpReqHead.token.getValue());
//兼容老的TOKEN头参数
if(StringUtils.isBlank(jwt)){
jwt=headers.get(HttpReqHead.token_old.getValue());
}
return jwt;
}
}java
import com.commnetsoft.auth.model.HttpReqHead;
import com.commnetsoft.commons.utils.StringUtils;
import com.commnetsoft.commons.utils.UriUtil;
import com.commnetsoft.core.CommonError;
import com.commnetsoft.core.CoreConstant;
import com.commnetsoft.exception.MicroRuntimeException;
import com.commnetsoft.zuul.RouteRuntimeException;
import com.commnetsoft.zuul.UriType;
import com.commnetsoft.zuul.service.AuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 内部接口地址处理器实现类<br/>
* http://127.0.0.1:8080/auth/test.fn<br/>
* 调用方需在Http头中传递<br>
* X-Commnet-Manage: 密钥 MD5 字符串
*
* @author Brack.zhu
* @date 2020/6/2
*/
@Component
public class InternalApiUriHandler implements IUriHandler {
/**
* Feign内部调用URL接口后缀 .fn
*/
public static final String INTERNAL_URL_SUFFIX = "fn";
private List<String> headerKeys;
@Autowired
private AuthService authService;
public InternalApiUriHandler() {
headerKeys = new ArrayList<>(3);
headerKeys.add(HttpReqHead.manage.getValue());
headerKeys.add(CoreConstant.Http.HEADER_REAL_IP);
//未经过Nginx
headerKeys.add(EXTEND_HEADER_REQUEST_REMOTE_ADDRESS);
}
@Override
public UriType handlerType() {
return UriType.INTERNAL_API_URI;
}
@Override
public List<String> headerKeys() {
return headerKeys;
}
@Override
public boolean isBodyData(String contentType) {
return false;
}
@Override
public Map<String, String> verifyUri(String uri, String method, Map<String, String> headers, InputStream in) {
//是否管理后台调用
try {
String manageKey = getHeaderManage(headers);
if (StringUtils.isBlank(manageKey)) {
throw new RouteRuntimeException(CommonError.illegal_operation,"非法访问,无管理密钥鉴权", HttpStatus.FORBIDDEN);
}
String ip = getHeaderIp(headers);
return authService.internalUriVerify(uri, method, manageKey, ip);
}catch (RouteRuntimeException rre){
throw rre;
}catch (MicroRuntimeException mre) {
throw new RouteRuntimeException(mre, HttpStatus.FORBIDDEN);
}
}
@Override
public boolean isSupport(String uri) {
String ext = UriUtil.getFileExtension(uri);
if (StringUtils.isNotBlank(ext) && INTERNAL_URL_SUFFIX.equals(ext)) {
return true;
}
return false;
}
String getHeaderManage(Map<String, String> headers) {
if (null == headers) {
return null;
}
return headers.get(HttpReqHead.manage.getValue());
}
}java
import com.commnetsoft.auth.model.HttpReqHead;
import com.commnetsoft.commons.utils.StringUtils;
import com.commnetsoft.commons.utils.UriUtil;
import com.commnetsoft.core.CommonError;
import com.commnetsoft.core.CoreConstant;
import com.commnetsoft.exception.MicroRuntimeException;
import com.commnetsoft.zuul.RouteRuntimeException;
import com.commnetsoft.zuul.UriType;
import com.commnetsoft.zuul.service.AuthService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 开放接口地址处理器实现类
*
* @author Brack.zhu
* @date 2020/6/2
*/
@Component
public class OpenApiUriHandler implements IUriHandler {
@Autowired
private AuthService authService;
private List<String> headerKeys;
private Logger log = LoggerFactory.getLogger(OpenApiUriHandler.class);
public OpenApiUriHandler() {
headerKeys = new ArrayList<>(6);
headerKeys.add(HttpReqHead.servicecode.getValue());
headerKeys.add(HttpReqHead.time.getValue());
headerKeys.add(HttpReqHead.sign.getValue());
//兼容老的
headerKeys.add(HttpReqHead.sign_old.getValue());
headerKeys.add(CoreConstant.Http.HEADER_REAL_IP);
headerKeys.add(EXTEND_HEADER_REQUEST_REMOTE_ADDRESS);
}
/**
* 开放接口地址前缀
*/
public static final String OPEN_API_PATH = "open";
@Override
public UriType handlerType() {
return UriType.OPEN_API_URI;
}
@Override
public List<String> headerKeys() {
return headerKeys;
}
@Override
public boolean isBodyData(String contentType) {
//application/json;charset=UTF-8 类型请求传入 请求流
if (StringUtils.isBlank(contentType) ||
(contentType.startsWith(MediaType.APPLICATION_JSON_UTF8_VALUE)
|| contentType.startsWith(MediaType.APPLICATION_JSON_VALUE)
|| contentType.startsWith(MediaType.APPLICATION_FORM_URLENCODED_VALUE))) {
return true;
}
log.warn("开放接口请求contentType:{}类型无效,不获取请求body流;仅支持空和{},{},{}", contentType, MediaType.APPLICATION_JSON_UTF8_VALUE, MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
return false;
}
@Override
public Map<String, String> verifyUri(String uri, String method, Map<String, String> headers, InputStream in) {
try {
String sign = getHeaderSign(headers);
if (StringUtils.isEmpty(sign)) {
//无签名数据直接返回
throw new RouteRuntimeException(CommonError.illegal_args,"无sign签名数据",HttpStatus.FORBIDDEN);
}
String serviceCode = getHeaderServiceCode(headers);
String time = getHeaderTime(headers);
String ip = getHeaderIp(headers);
return authService.openUriVerify(serviceCode, time, sign, ip, uri, method, in);
} catch (RouteRuntimeException rre) {
log.error("URI地址权限校验路由错误:", rre);
throw rre;
} catch (MicroRuntimeException mre) {
log.error("URI地址权限校验错误:", mre);
throw new RouteRuntimeException(mre,HttpStatus.FORBIDDEN);
} catch (Exception e) {
log.error("URI地址权限校验内部错误:", e);
throw new RouteRuntimeException(CommonError.internal_error,e.getMessage(),HttpStatus.FORBIDDEN);
}
}
@Override
public boolean isSupport(String uri) {
try {
String[] paths = UriUtil.getPaths(new URI(uri));
if (null != paths && paths.length > 2) {
// 格式如 /open/*****
String path = paths[0];
if (OPEN_API_PATH.equals(path)) {
return true;
}
// 格式如 /api/open/*****
path = paths[1];
if (OPEN_API_PATH.equals(path)) {
return true;
}
}
} catch (URISyntaxException e) {
log.error("URL地址({})转换异常:", uri, e);
}
return false;
}
String getHeaderServiceCode(Map<String, String> headers) {
if (null == headers) {
return null;
}
return headers.get(HttpReqHead.servicecode.getValue());
}
String getHeaderTime(Map<String, String> headers) {
if (null == headers) {
return null;
}
return headers.get(HttpReqHead.time.getValue());
}
String getHeaderSign(Map<String, String> headers) {
if (null == headers) {
return null;
}
String sign = headers.get(HttpReqHead.sign.getValue());
if (StringUtils.isBlank(sign)) {
//兼容老的
sign = headers.get(HttpReqHead.sign_old.getValue());
}
return sign;
}
}java
import com.commnetsoft.commons.utils.StringUtils;
import com.commnetsoft.commons.utils.UriUtil;
import com.commnetsoft.zuul.UriType;
import org.springframework.stereotype.Component;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 资源地址处理器实现类<br/>
* <ui>
* <li>.ws 放行</li>
* </ui>
*
*
* @author Brack.zhu
* @date 2020/6/2
*/
@Component
public class ResourceUriHandler implements IUriHandler {
/**
* 排除放行地址后缀集合
*/
public List<String> excludeFileExtensions = null;
/**
* 白名单地址集合
*/
public List<String> whiteUris = null;
/**
* 黑名单地址集合
*/
public List<String> blackUris = null;
public ResourceUriHandler() {
excludeFileExtensions = new ArrayList<>(1);
//.fn地址不放行
excludeFileExtensions.add(InternalApiUriHandler.INTERNAL_URL_SUFFIX);
whiteUris = new ArrayList<>(4);
whiteUris.add("/v2/api-docs");
whiteUris.add("/swagger-resources");
whiteUris.add("/swagger-resources/configuration/security");
whiteUris.add("/swagger-resources/configuration/ui");
}
@Override
public UriType handlerType() {
return UriType.RESOURCE_URI;
}
@Override
public List<String> headerKeys() {
return null;
}
@Override
public boolean isBodyData(String contentType) {
return false;
}
@Override
public Map<String, String> verifyUri(String uri, String method, Map<String, String> headers, InputStream in) {
//资源类型直接放行
return null;
}
@Override
public boolean isSupport(String uri) {
//白名单地址本处理器处理
if (isWhiteUri(uri)) {
return true;
}
//黑名单地址本处理不处理---交给其他处理器处理
if (isBlackUri(uri)) {
return false;
}
String ext = UriUtil.getFileExtension(uri);
if (StringUtils.isNotBlank(ext) && !excludeFileExtensions.contains(ext)) {
//带资源文件类型且不是内部接口的统统放行
return true;
}
return false;
}
/**
* 是否白名单
*
* @param uri
* @return
*/
boolean isWhiteUri(String uri) {
if (null != whiteUris) {
for (String whiteUri : whiteUris) {
if (uri.endsWith(whiteUri)) {
return true;
}
}
}
return false;
}
/**
* 是否黑名单
*
* @param uri
* @return
*/
boolean isBlackUri(String uri) {
if (null != blackUris) {
for (String blackUri : blackUris) {
if (uri.endsWith(blackUri)) {
return true;
}
}
}
return false;
}
}java
import com.commnetsoft.commons.utils.StringUtils;
import com.commnetsoft.commons.utils.UriUtil;
import com.commnetsoft.core.CommonError;
import com.commnetsoft.zuul.RouteRuntimeException;
import com.commnetsoft.zuul.UriType;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
/**
* Websocket 地址处理器
* @author Brack.zhu
* @date 2020/6/16
*/
@Component
public class WebsocketUriHandler implements IUriHandler{
/**
* WEBSOCKET内部调用URL接口后缀 .ws
*/
public static final String WEBSOCKET_URL_SUFFIX = ".ws";
@Override
public UriType handlerType() {
return UriType.WEBSOCKET_URI;
}
@Override
public boolean isSupport(String uri) {
String ext = UriUtil.getFileExtension(uri);
if (StringUtils.isNotBlank(ext) && WEBSOCKET_URL_SUFFIX.equals(ext)) {
//ws接口类型支持
return true;
}
return false;
}
@Override
public List<String> headerKeys() {
return null;
}
@Override
public boolean isBodyData(String contentType) {
return false;
}
@Override
public Map<String, String> verifyUri(String uri, String method, Map<String, String> headers, InputStream in) {
//该路由服务禁止一切ws接口访问,Websocket访问使用Gateway路由
throw new RouteRuntimeException(CommonError.illegal_operation,"该路由不支持WS通讯",HttpStatus.FORBIDDEN);
}
}